{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XNWJ6JVGkOlf"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors. [Licensed under the Apache License, Version 2.0](#scrollTo=bPJq2qP2KE3u)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "fSlQ2vFzKGOY"
      },
      "outputs": [],
      "source": [
        "// #@title Licensed under the Apache License, Version 2.0 (the \"License\"); { display-mode: \"form\" }\n",
        "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "// you may not use this file except in compliance with the License.\n",
        "// You may obtain a copy of the License at\n",
        "//\n",
        "// https://www.apache.org/licenses/LICENSE-2.0\n",
        "//\n",
        "// Unless required by applicable law or agreed to in writing, software\n",
        "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "// See the License for the specific language governing permissions and\n",
        "// limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yfNdITLmJtX8"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/swift/tutorials/raw_tensorflow_operators\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />TensorFlow.org에서 보기</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/swift/tutorials/raw_tensorflow_operators.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />구글 코랩(Colab)에서 실행하기</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ko/swift/tutorials/raw_tensorflow_operators.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />깃허브(GitHub)소스 보기</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/swift/tutorials/raw_tensorflow_operators.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bBxnTS5bBk2d"
      },
      "source": [
        "Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역 활동의 특성상 정확한 번역과 최신 내용을 반영하기 위해 노력함에도\n",
        "불구하고 [공식 영문 문서](https://www.tensorflow.org/?hl=en)의 내용과 일치하지 않을 수 있습니다.\n",
        "이 번역에 개선할 부분이 있다면\n",
        "[tensorflow/docs-l10n](https://github.com/tensorflow/docs-l10n/) 깃헙 저장소로 풀 리퀘스트를 보내주시기 바랍니다.\n",
        "문서 번역이나 리뷰에 참여하려면\n",
        "[docs-ko@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ko)로\n",
        "메일을 보내주시기 바랍니다."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lONNcRalVUO9"
      },
      "source": [
        "# Raw 텐서플로 연산자\n",
        "\n",
        "스위프트를 위한 텐서플로는 텐서플로를 기반으로 API 디자인에 새로운 접근을 할 수 있게 합니다. API들은 확립된 라이브러리들로 부터 세밀하게 조직되어 있고, 새로운 관용구로 결합되어 있습니다. 이것은 모든 텐서플로우 API들이 직접적으로 Swift APIs로 사용되어질 수 있는 것은 아니라는 걸 뜻하고, 또 우리의 API 큐레이션이 상당한 시간과 발전 시키기 위한 헌신적인 노력이 필요하다는 것을 의미합니다. 만약 당신의 가장 좋아하는 텐서플로우 연산자가 Swift에서 사용 가능 하지 않는다고 해도 걱정하지 마세요. – 텐서플로우 Swift 라이브러리는 당신에게 Raw 네임스페이스 아래에서 대부분의 텐서플로우 연산자에 접근할 수 있도록 합니다.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CYqNvcHxqg0Y"
      },
      "source": [
        "`텐서플로`를 시작하기 위해 불러오세요."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cVRrzjzFqee9"
      },
      "outputs": [],
      "source": [
        "import TensorFlow"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5vza91sR09r-"
      },
      "source": [
        "## Raw 연산자 호출하기\n",
        "\n",
        "코드 완성기능을 통해 `Raw` 네임스페이스에서 당신이 필요한 함수를 찾으세요."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "kZRlD4utdPuX"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[10.0, 18.0]\n"
            ]
          },
          "execution_count": 3,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "Raw.mul(Tensor([2.0, 3.0]), Tensor([5.0, 6.0]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iIgKg-ueVCy_"
      },
      "source": [
        "## 새로운 곱셈 연산자를 정의하기\n",
        "\n",
        "곱셈은 이미 `Tensor` 에서 `*` 연산자로 사용이 가능하지만, `.*`라는 새로운 이름의 연산자로 이용 가능 할 수 있도록 만들고 싶다고 가정해봅시다. 스위프트는 당신이 소급적으로 메소드를 추가할 수 있도록 하거나 `extension` 선언을 사용하는 타입들이 존재할 가능성을 계산할 수 있게 해줍니다.\n",
        "\n",
        "지금, extension을 선언하여 `.*`연산자를 `Tensor`에 추가해봅시다. 그리고 tensor의 `Scalar` 타입이 [`Numeric`](https://developer.apple.com/documentation/swift/numeric)을 따를 때 이용 가능하도록 만드세요."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "BdH-yZBjTZNx"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[[ 8.0, 14.0],\n",
              " [18.0, 20.0]]\n"
            ]
          },
          "execution_count": 4,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "infix operator .* : MultiplicationPrecedence\n",
        "\n",
        "extension Tensor where Scalar: Numeric {\n",
        "    static func .* (_ lhs: Tensor, _ rhs: Tensor) -> Tensor {\n",
        "        return Raw.mul(lhs, rhs)\n",
        "    }\n",
        "}\n",
        "\n",
        "let x: Tensor<Double> = [[1.0, 2.0], [3.0, 4.0]]\n",
        "let y: Tensor<Double> = [[8.0, 7.0], [6.0, 5.0]]\n",
        "x .* y"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ucD5XZYYyzNe"
      },
      "source": [
        "## 래퍼 함수에서 파생된 것을 정의하기\n",
        "\n",
        "당신은 쉽게 스위프트 API를 다듬어지지 않은 텐서플로우 연산자에서 정의할 수 있을 뿐만 아니라, 스위프트가 가지고 있는 최고 수준의 일급 자동 미분 기능을 이용하여 Raw 텐서플로우 연산자를 미분할 수 있습니다.\n",
        "\n",
        "`.*`연산자를 미분 가능하게 만들기 위해서, `@differentiable` 속성을 이용하세요. 그리고 `vjp:` 레이블에서 고안된 함수를 속성 인자로써 구체화 시키세요. `.*`연산자가 제네릭 타입의 `Scalar`가 `Numeric`를 따르도록 정의되었기 때문에, `Tensor<Scalar>`가 `Differentiable` 프로토콜을 따르도록 만들기엔 충분하지(적절하지) 않습니다. 타입 세이프티를 지키는, 스위프트는 우리에게 `@differentiable` 속성의 `Scalar`가  `TensorFlowFloatingPoint` 프로토콜을 따르도록 요구하기 위해서, 제네릭 제약 조건을 추가하도록 요구할 것입니다. `TensorFlowFloatingPoint`는 `Tensor<Scalar>`가 `Differentiable`을 따르도록 만드는 프로토콜 입니다.\n",
        "\n",
        "```swift\n",
        "@differentiable(vjp: multiplyDerivative where Scalar: TensorFlowFloatingPoint)\n",
        "```"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "fDXS0h_YumcL"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "▿ 2 elements\n",
              "  - .0 : [[8.0, 7.0],\n",
              " [6.0, 5.0]]\n",
              "  - .1 : [[1.0, 2.0],\n",
              " [3.0, 4.0]]\n"
            ]
          },
          "execution_count": 5,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "infix operator .* : MultiplicationPrecedence\n",
        "\n",
        "extension Tensor where Scalar: Numeric {\n",
        "    @differentiable(vjp: multiplyDerivative where Scalar: TensorFlowFloatingPoint)\n",
        "    static func .* (_ lhs: Tensor,  _ rhs: Tensor) -> Tensor {\n",
        "        return Raw.mul(lhs, rhs)\n",
        "    }\n",
        "}\n",
        "\n",
        "extension Tensor where Scalar : TensorFlowFloatingPoint { \n",
        "    static func multiplyDerivative(\n",
        "        _ lhs: Tensor, _ rhs: Tensor\n",
        "    ) -> (Tensor, (Tensor) -> (Tensor, Tensor)) {\n",
        "        return (lhs * rhs, { v in\n",
        "            ((rhs * v).unbroadcasted(to: lhs.shape),\n",
        "            (lhs * v).unbroadcasted(to: rhs.shape))\n",
        "        })\n",
        "    }\n",
        "}\n",
        "\n",
        "// 이제, 우리는 방금 정의한 `.*`연산자를 호출하는 함수의 도함수를 구할 수 있습니다.\n",
        "gradient(at: x, y) { x, y in\n",
        "    (x .* y).sum()\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l7kae5o1VKnu"
      },
      "source": [
        "## 더 많은 예제들"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "v92FrXpCSuLT"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[[ 7.0, 15.0],\r\n",
            " [10.0, 22.0]]\r\n",
            "[[10.0, 14.0],\r\n",
            " [14.0, 20.0]]\r\n",
            "[[ 5.0, 11.0],\r\n",
            " [11.0, 25.0]]\r\n",
            "[[ 7.0, 10.0],\r\n",
            " [15.0, 22.0]]\r\n"
          ]
        }
      ],
      "source": [
        "let matrix = Tensor<Float>([[1, 2], [3, 4]])\n",
        "\n",
        "print(Raw.matMul(matrix, matrix, transposeA: true, transposeB: true))\n",
        "print(Raw.matMul(matrix, matrix, transposeA: true, transposeB: false))\n",
        "print(Raw.matMul(matrix, matrix, transposeA: false, transposeB: true))\n",
        "print(Raw.matMul(matrix, matrix, transposeA: false, transposeB: false))"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "raw_tensorflow_operators.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Swift",
      "name": "swift"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
